package com.scs.application.modules.dept.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.modules.base.entity.Warehouse;
import com.scs.application.modules.base.service.DeptService;
import com.scs.application.modules.base.service.WarehouseService;
import com.scs.application.modules.dept.entity.DailyBalance;
import com.scs.application.modules.dept.entity.DailyBalanceItem;
import com.scs.application.modules.dept.entity.MonthlyBalance;
import com.scs.application.modules.dept.entity.MonthlyBalanceItem;
import com.scs.application.modules.dept.mapper.MonthlyBalanceMapper;
import com.scs.application.modules.dept.service.DailyBalanceItemService;
import com.scs.application.modules.dept.service.DailyBalanceService;
import com.scs.application.modules.dept.service.MonthlyBalanceItemService;
import com.scs.application.modules.dept.service.MonthlyBalanceService;
import com.scs.application.modules.finance.entity.Period;
import com.scs.application.modules.finance.service.PeriodService;
import com.scs.application.modules.wm.dto.DailyOrderKey;
import com.scs.application.modules.wm.service.StockService;
import com.scs.application.modules.wm.service.WorkOrderItemService;
import com.scs.application.modules.wm.service.WorkOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 仓库月结表 服务实现类
 * </p>
 */
@Service
public class MonthlyBalanceServiceImpl extends BaseServiceImpl<MonthlyBalanceMapper, MonthlyBalance> implements MonthlyBalanceService {

    @Autowired
    private StockService stockService;

    @Autowired
    private PeriodService periodService;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private WorkOrderItemService workOrderItemService;
    @Autowired
    private WarehouseService warehouseService;
    @Autowired
    private DailyBalanceService dailyBalanceService;

    @Autowired
    private DailyBalanceItemService dailyBalanceItemService;

    @Autowired
    private MonthlyBalanceItemService monthlyBalanceItemService;
    @Autowired
    private DeptService deptService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void syncMonthlyBalance() {
        List<Period> periods = periodService.list();
        List<Warehouse> list = warehouseService.list();
        for (Warehouse warehouse : list) {
            periods.forEach(p -> addMonthlyBalance(warehouse.getId(), p));
        }
    }

    @Override
    public void delete(List<String> ids) {
        if(ids.isEmpty()){
            return;
        }
        this.removeByIds(ids);
        monthlyBalanceItemService.remove(Wrappers.<MonthlyBalanceItem>query().in("dept_monthly_balance_id", ids));
    }

    public void addMonthlyBalance(String warehouseId, Period period) {
//        List<MonthlyBalance> monthlyBalanceList = this.list(Wrappers.<MonthlyBalance>query()
//                .eq("period", period.getPeriod()).eq("warehouse_id", warehouseId));
//        if(monthlyBalanceList.size() > 0) {
//            if(!monthlyBalanceList.get(0).getFlowStatus().equals(GlobalConsts.FLOW_START_VALUE)) {
//                return;
//            }
//            delete(monthlyBalanceList.stream().map(o -> o.getId()).collect(Collectors.toList()));
//        }
//        // 月结数据
//        List<MonthlyBalanceItem> monthlyBalanceItems = new ArrayList<>();
//        MonthlyBalanceItem monthlyBalanceItem;
//        // 上一月主表数据
//        List<Period> periodList = periodService.list(Wrappers.<Period>query().eq("end_date", period.getStartDate()));
//        String beforePeriod;
//        if (periodList.isEmpty()){
//            beforePeriod = "0";
//        }else {
//            beforePeriod = periodList.get(0).getPeriod();
//        }
//
//        List<MonthlyBalance> mbList = this.list(Wrappers.<MonthlyBalance>query()
//                .eq("period", beforePeriod).eq("warehouse_id", warehouseId));
//        Map<String, Double> mbiMap = new HashMap<>();
//        if (!mbList.isEmpty()){
//            // 上一月明细数据
//            List<MonthlyBalanceItem> monthlyBalanceItemList = monthlyBalanceItemService.list(Wrappers.<MonthlyBalanceItem>query()
//                    .in("dept_monthly_balance_id", mbList.stream().map(o -> o.getId()).collect(Collectors.toList())));
//            mbiMap = monthlyBalanceItemList.stream()
//                    .collect(Collectors.toMap(MonthlyBalanceItem::getMatrId,MonthlyBalanceItem::getQty9,(o1, o2) -> o1));
//        }
//
//        // 出入库数据汇总
//        List<WorkOrder> workOrderList = workOrderService.list(Wrappers.<WorkOrder>query()
//                .between("bus_date", period.getStartDate(), period.getEndDate()).eq("warehouse_id", warehouseId));
//        // 获取当前月的入库单ids
//        List<String> inIds = workOrderList.stream().filter(o -> GlobalConsts.ORDER_DIRECTION_IN.equals(o.getDirection()))
//                .map(o -> o.getId()).collect(Collectors.toList());
//        // 获取当前月的出库单ids
//        List<String> outIds = workOrderList.stream().filter(o -> GlobalConsts.ORDER_DIRECTION_OUT.equals(o.getDirection()))
//                .map(o -> o.getId()).collect(Collectors.toList());
//        // 入库数量
//        Map<String, Double> inQtyMap =dailyBalanceService.inOutUtil(inIds);
//        // 出库数量
//        Map<String, Double> outQtyMap =dailyBalanceService.inOutUtil(outIds);
//
//        // 库存数据汇总
//        List<Stock> stockList = stockService.list(Wrappers.<Stock>query().eq("warehouse_id", warehouseId));
//        Map<String, List<Stock>> stockMap = stockList.stream().collect(
//                Collectors.groupingBy(o -> o.getMatrId()));
//        // 期末数量
//        Map<String, Double> stockQtyMap = new HashMap<>();
//
//        // 月结主表
//        List<Dept> deptList = deptService.list(Wrappers.<Dept>query().eq("warehouse_id", warehouseId));
//        if (deptList.isEmpty()){
//            return;
//        }
//        Dept dept = deptList.get(0);
//        MonthlyBalance monthlyBalance = new MonthlyBalance()
//                .setPeriod(period.getPeriod()).setWarehouseId(warehouseId).setWarehouseName(dept.getWarehouseName())
//                .setDeptId(dept.getId()).setDeptName(dept.getName());
//        this.save(monthlyBalance);
//        for (String s : stockMap.keySet()) {
//            monthlyBalanceItem = new MonthlyBalanceItem();
//            List<Stock> values = stockMap.get(s);
//            // 当前库存
//            double qty = values.stream().mapToDouble(Stock::getSkuQty).sum();
//            stockQtyMap.put(s, qty);
//            Stock stock = values.get(0);
//            monthlyBalanceItem.setMatrId(stock.getMatrId()).setDeptMonthlyBalanceId(monthlyBalance.getId())
//                    .setMatrSpec(stock.getMatrSpec()).setMatrName(stock.getMatrName()).setPeriod(period.getPeriod()).setQty9(qty)
//                    .setQty0(mbiMap.get(s) == null ? qty : mbiMap.get(s)).setQtyIn(inQtyMap.get(s) == null ? 0.0 : inQtyMap.get(s))
//                    .setQtyOut(outQtyMap.get(s) == null ? 0.0 : outQtyMap.get(s));
//            monthlyBalanceItems.add(monthlyBalanceItem);
//        }
//
//        // 删除当前期号 当前科室的月结数据
//
//        monthlyBalanceItemService.saveBatch(monthlyBalanceItems);

    }

    @Override
    public Page<?> page(QueryContext context) {
        Map<String, Object> params = context.getParams();
        if (params == null){
            return super.page(context);
        }

        Object warehouseId = params.get("warehouseId");
        if (warehouseId == null){
            return super.page(context);
        }

        List<MonthlyBalance> list = this.list(Wrappers.<MonthlyBalance>query().eq("warehouse_id", warehouseId));
        if (list.isEmpty()){
            throw new BusinessException("没有对应库存地");
        }
        return super.page(context);
    }



    @Override
    public MonthlyBalance saveMonthlBalance(MonthlyBalance monthlyBalance) {
        List<DailyBalance> itemList = dailyBalanceService.list(new QueryWrapper<DailyBalance>()
                .between("balance_date", DateUtils.format(monthlyBalance.getBeginDate(), "yyyy-MM-dd"),
                        DateUtils.format(monthlyBalance.getEndDate(), "yyyy-MM-dd"))
                .eq("warehouse_id", monthlyBalance.getWarehouseId()).orderByAsc("balance_date"));

        if (itemList.isEmpty()) {
            throw new BusinessException("当前时间区间没有数据,请重新查询");
        }
        List<MonthlyBalance> list = this.list(new QueryWrapper<MonthlyBalance>()
                .eq("warehouse_id", monthlyBalance.getWarehouseId())
                .eq("begin_date", DateUtils.format(monthlyBalance.getBeginDate(), "yyyy-MM-dd"))
                .eq("end_date", DateUtils.format(monthlyBalance.getEndDate(), "yyyy-MM-dd"))
        );
        if (!list.isEmpty()) {
            delete(list.stream().map(o -> o.getId()).collect(Collectors.toList()));

        }

        List<String> dailyItemList = itemList.stream().map(DailyBalance::getId).collect(Collectors.toList());
        DailyBalance dailyBalanceBeginDate = itemList.get(0);
        DailyBalance dailyBalanceEndDate = itemList.get(itemList.size() - 1);
        monthlyBalance
                .setAmountBeginSum(dailyBalanceBeginDate.getAmountBeginSum())
                .setQtyBeginSum(dailyBalanceBeginDate.getQtyBeginSum())
                .setAmountEndSum(dailyBalanceEndDate.getAmountEndSum())
                .setQtyEndSum(dailyBalanceEndDate.getQtyEndSum())
                .setQtyConsumeOutSum(itemList.stream().mapToDouble(o -> o.getQtyConsumeOutSum() == null ? 0.0 : o.getQtyConsumeOutSum()).sum())
                .setAmountConsumeOutSum(itemList.stream().mapToDouble(o -> o.getAmountConsumeOutSum() == null ? 0.0 : o.getAmountConsumeOutSum()).sum())
                .setQtyOutSum(itemList.stream().mapToDouble(o -> o.getQtyOutSum() == null ? 0.0 : o.getQtyOutSum()).sum())
                .setAmountOutSum(itemList.stream().mapToDouble(o -> o.getAmountOutSum() == null ? 0.0 : o.getAmountOutSum()).sum())
                .setAmountInSum(itemList.stream().mapToDouble(o -> o.getAmountInSum() == null ? 0.0 : o.getAmountInSum()).sum())
                .setQtyInSum(itemList.stream().mapToDouble(o -> o.getQtyInSum() == null ? 0.0 : o.getQtyInSum()).sum())
                .setAmountChargingSum(itemList.stream().mapToDouble(o -> o.getAmountChargingSum() == null ? 0.0 : o.getAmountChargingSum()).sum())
                .setQtyChargingSum(itemList.stream().mapToDouble(o -> o.getQtyChargingSum() == null ? 0.0 : o.getQtyChargingSum()).sum());
        this.save(monthlyBalance);
        List<DailyBalanceItem> dailyItems = dailyBalanceItemService.list(new QueryWrapper<DailyBalanceItem>()
                .in("dept_daily_balance_id", dailyItemList).orderByAsc("balance_date"));

        Map<DailyOrderKey, List<DailyBalanceItem>> items = dailyItems.stream().collect(
                Collectors.groupingBy(o -> new DailyOrderKey(o.getSupplierId(), o.getMatrId(), o.getFlagOmoc())));
        DailyBalanceItem balanceItem = new DailyBalanceItem();
        for (DailyOrderKey orderKey : items.keySet()) {
            MonthlyBalanceItem monthlyBalanceItem = new MonthlyBalanceItem();
            List<DailyBalanceItem> dailyBalanceItems = items.get(orderKey);
//            期初
            DailyBalanceItem beginItem = dailyBalanceItems.stream().filter(o -> o.getBalanceDate()
                    .equals(dailyBalanceBeginDate.getBalanceDate())).findAny().orElse(balanceItem);
//          期末
            DailyBalanceItem endItem  = dailyBalanceItems.stream().filter(o -> o
                    .getBalanceDate().equals(dailyBalanceEndDate.getBalanceDate())).findAny().orElse(balanceItem);

            DailyBalanceItem dailyBalanceItem = dailyBalanceItems.get(0);
            monthlyBalanceItem.setMatrId(orderKey.getMatrId())
                    .setDeptMonthlyBalanceId(monthlyBalance.getId())
                    .setMatrSpec(dailyBalanceItem.getMatrSpec())
                    .setMatrName(dailyBalanceItem.getMatrName())
                    .setMatrModel(dailyBalanceItem.getMatrModel())
                    .setBeginDate(monthlyBalance.getBeginDate())
                    .setEndDate(monthlyBalance.getEndDate())
                    .setFlagOmoc(dailyBalanceItem.getFlagOmoc())
                    .setSupplierId(dailyBalanceItem.getSupplierId())
                    .setSupplierName(dailyBalanceItem.getSupplierName())
                    .setAmountBegin(beginItem.getAmountBegin() == null ? 0.0 : beginItem.getAmountBegin())
                    .setQtyBegin(beginItem.getQtyBegin() == null ? 0.0 : beginItem.getQtyBegin())
                    .setAmountEnd(endItem.getAmountEnd() == null ? 0.0 : endItem.getAmountEnd())
                    .setQtyEnd(endItem.getQtyEnd() == null ? 0.0 : endItem.getQtyEnd())
                    .setQtyConsumeOut(dailyBalanceItems.stream().mapToDouble(o -> o.getQtyConsumeOut() == null ? 0.0 : o.getQtyConsumeOut()).sum())
                    .setAmountConsumeOut(dailyBalanceItems.stream().mapToDouble(o -> o.getAmountConsumeOut() == null ? 0.0 : o.getAmountConsumeOut()).sum())
                    .setQtyOut(dailyBalanceItems.stream().mapToDouble(o -> o.getQtyOut() == null ? 0.0 : o.getQtyOut()).sum())
                    .setAmountOut(dailyBalanceItems.stream().mapToDouble(o -> o.getAmountOut() == null ? 0.0 : o.getAmountOut()).sum())
                    .setAmountIn(dailyBalanceItems.stream().mapToDouble(o -> o.getAmountIn() == null ? 0.0 : o.getAmountIn()).sum())
                    .setQtyIn(dailyBalanceItems.stream().mapToDouble(o -> o.getQtyIn() == null ? 0.0 : o.getQtyIn()).sum())
                    .setAmountCharging(dailyBalanceItems.stream().mapToDouble(o -> o.getAmountCharging() == null ? 0.0 : o.getAmountCharging()).sum())
                    .setQtyCharging(dailyBalanceItems.stream().mapToDouble(o -> o.getQtyCharging() == null ? 0.0 : o.getQtyCharging()).sum())
                    .setAmountModify(dailyBalanceItems.stream().mapToDouble(o -> o.getAmountModify() == null ? 0.0 : o.getAmountModify()).sum())
                    .setQtyModify(dailyBalanceItems.stream().mapToDouble(o -> o.getQtyModify() == null ? 0.0 : o.getQtyModify()).sum())
                    .setAmountAbnormal(dailyBalanceItems.stream().mapToDouble(o -> o.getAmountAbnormal() == null ? 0.0 : o.getAmountAbnormal()).sum())
                    .setQtyAbnormal(dailyBalanceItems.stream().mapToDouble(o -> o.getQtyAbnormal() == null ? 0.0 : o.getQtyAbnormal()).sum());
            monthlyBalanceItemService.save(monthlyBalanceItem);
        }
        return monthlyBalance;
    }
}
